
#include "soft_io_spi.h"

static const uint8_t mask[] = {(1<<7), (1<<6),(1<<5),(1<<4),(1<<3),(1<<2),(1<<1),(1<<0)};

static void SpiSwInit(SPI_SW* spi_sw)
{
	spi_sw->intface.pin_init();
	spi_sw->intface.sclk_out_h();
}

static uint8_t SpiSwMasterTransferByte(SPI_SW* spi_sw, uint8_t send_data)
{
    uint8_t i;
    uint8_t read_data = 0;

    for(i=0; i<8; i++){
/*************************************************************/
		if(spi_sw->prarm.cpha == 0){
			if((send_data & mask[i]) != 0){
				spi_sw->intface.mosi_out_h();
			}
			else{
				spi_sw->intface.mosi_out_l();
			}
			spi_sw->intface.delay();
		}
/*************************************************************/
		if(spi_sw->prarm.cpol == 0){
			spi_sw->intface.sclk_out_h();	
		}
		else{
			spi_sw->intface.sclk_out_l();			//CLK high when idle		
		}
/*************************************************************/
		if(spi_sw->prarm.cpha == 0){
			read_data <<= 1;
			if(spi_sw->intface.miso_in() != 0){
				read_data |= 0x01;
			}
		}
		else{
			if((send_data & mask[i]) != 0){
				spi_sw->intface.mosi_out_h();
			}
			else{
				spi_sw->intface.mosi_out_l();
			}
		}
		spi_sw->intface.delay();
/*************************************************************/
		if(spi_sw->prarm.cpol == 0){
			spi_sw->intface.sclk_out_l();	
		}
		else{
			spi_sw->intface.sclk_out_h();		
		}	
/*************************************************************/
		if(spi_sw->prarm.cpha == 1){
			read_data <<= 1;
			if(spi_sw->intface.miso_in() != 0){
				read_data |= 0x01;
			}
			spi_sw->intface.delay();
		}
/*************************************************************/
    }
	
	spi_sw->intface.delay();	//delay time between every byte
	spi_sw->intface.delay();
	
    return read_data;
}

void SpiSwStructInit(SPI_SW* spi_sw, SPI_SW_PRARM prm, SPI_SW_INTERFACE intface)
{
	spi_sw->prarm = prm;
	spi_sw->intface = intface;
	
	spi_sw->api.spi_sw_init = SpiSwInit;
	spi_sw->api.spi_sw_master_transfer_byte = SpiSwMasterTransferByte;
}


/********************************************************************************
 #include "em_cmu.h"
#include "em_gpio.h"
#include "hw_io_soft_spi.h"
 #define PORT_SPI_CLK 	gpioPortD   
#define PIN_SPI_CLK  	2

#define PORT_SPI_MISO 	gpioPortD   
#define PIN_SPI_MISO  	1

#define PORT_SPI_MOSI 	gpioPortD   
#define PIN_SPI_MOSI 	0

#define OP_SPI_CLK_H()		(GPIO->P[PORT_SPI_CLK].DOUTSET = (1 << PIN_SPI_CLK))
#define OP_SPI_CLK_L()      (GPIO->P[PORT_SPI_CLK].DOUTCLR = (1 << PIN_SPI_CLK))

#define OP_SPI_MOSI_H()		(GPIO->P[PORT_SPI_MOSI].DOUTSET = (1 << PIN_SPI_MOSI))
#define OP_SPI_MOSI_L()     (GPIO->P[PORT_SPI_MOSI].DOUTCLR = (1 << PIN_SPI_MOSI))

#define IN_SPI_MISO()		((GPIO->P[PORT_SPI_MISO].DIN & (1 << PIN_SPI_MISO)) ? 1 : 0)

void spi_pin_init(void)
{
    CMU_ClockEnable(cmuClock_GPIO, true);
	
	GPIO_PinModeSet(PORT_SPI_CLK, PIN_SPI_CLK, gpioModePushPull, 0);
	GPIO_PinModeSet(PORT_SPI_MOSI, PIN_SPI_MOSI, gpioModePushPull, 1);
	GPIO_PinModeSet(PORT_SPI_MISO, PIN_SPI_MISO, gpioModeWiredAndDrivePullUp, 1);
}

void spi_sclk_h(void)
{
	OP_SPI_CLK_H();
}
void spi_sclk_l(void)
{
	OP_SPI_CLK_L();
}
void spi_mosi_h(void)
{
	OP_SPI_MOSI_H();
}
void spi_mosi_l(void)
{
	OP_SPI_MOSI_L();
}
uint8_t spi_miso(void)
{
	return IN_SPI_MISO();
}

void spi_delay(void)
{
	unsigned int i = 6;
	
	do
	{
		i--;
	}
	while(i > 0);
}


SPI_SW spi;
void spi_struct_init(void)
{
	SPI_SW_PRARM prm;
	SPI_SW_INTERFACE intface;
	
	intface.pin_init = spi_pin_init;
	intface.sclk_out_h = spi_sclk_h;
	intface.sclk_out_l = spi_sclk_l;
	intface.mosi_out_h = spi_mosi_h;
	intface.mosi_out_l = spi_mosi_l;
	intface.miso_in = spi_miso;
	intface.delay = spi_delay;
		
	SpiSwStructInit(&spi, prm, intface);
}
***********************************************************/
/***********************************************************
void CS1258_SPI_CS_HIGH(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_12);
}

void CS1258_SPI_CS_LOW(void)
{
	GPIO_ResetBits(GPIOB, GPIO_Pin_12);
}

void CS1258_SPI_CLK_HIGH(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_13);
}

void CS1258_SPI_CLK_LOW(void)
{
	GPIO_ResetBits(GPIOB, GPIO_Pin_13);
}

void CS1258_SPI_OUT_HIGH(void)
{
	GPIO_SetBits(GPIOB, GPIO_Pin_14);
}

void CS1258_SPI_OUT_LOW(void)
{
	GPIO_ResetBits(GPIOB, GPIO_Pin_14);
}

uint8_t CS1258_SPI_IN(void)
{
	return 	GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14);
}

void CS1258_SPI_PIN_INIT(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); 
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_Init(GPIOB, &GPIO_InitStructure); 

  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14;
  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
  	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  	GPIO_Init(GPIOB, &GPIO_InitStructure); 
}

#include "soft_io_spi.h"
SPI_SW 				CS1258_spi;
SPI_SW_PRARM		CS1258_spi_prarm;
SPI_SW_INTERFACE	CS1258_spi_intfc;
void spi_init(void)
{
	CS1258_spi_intfc.delay = SPI_DELAY;
	CS1258_spi_intfc.miso_in = CS1258_SPI_IN;
	CS1258_spi_intfc.mosi_out_h = CS1258_SPI_OUT_HIGH;
	CS1258_spi_intfc.mosi_out_l = CS1258_SPI_OUT_LOW;
	CS1258_spi_intfc.sclk_out_h = CS1258_SPI_CLK_HIGH;
	CS1258_spi_intfc.sclk_out_l = CS1258_SPI_CLK_LOW;
	CS1258_spi_intfc.pin_init = CS1258_SPI_PIN_INIT;

	CS1258_spi_prarm.cpha = 1;
	CS1258_spi_prarm.cpol = 0;

	SpiSwStructInit(&CS1258_spi, CS1258_spi_prarm, CS1258_spi_intfc);
	CS1258_spi.api.spi_sw_init(&CS1258_spi);
}

void spi_demo(void)
{
	CS1258_SPI_CS_LOW();
	CS1258_spi.api.spi_sw_master_transfer_byte(&CS1258_spi, 0X80);
	CS1258_spi.api.spi_sw_master_transfer_byte(&CS1258_spi, 0xAA);
	CS1258_SPI_CS_HIGH();
	delay_ms(10);

	CS1258_SPI_CS_LOW();
	CS1258_spi.api.spi_sw_master_transfer_byte(&CS1258_spi, 0XEA);
	read_data = CS1258_spi.api.spi_sw_master_transfer_byte(&CS1258_spi, 0xff);
	CS1258_SPI_CS_HIGH();
	delay_ms(10);
	USART_Tx(read_data);
	delay_ms(10);
}

**************************************************/


